//// Copyright 2000-2024 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license.
//package com.linqingying.gitcode.pullrequest.ui.editor
//
//import com.intellij.collaboration.async.launchNow
//import com.intellij.collaboration.async.mapScoped
//import com.intellij.collaboration.async.nestedDisposable
//import com.intellij.collaboration.ui.codereview.diff.DiscussionsViewOption
//import com.intellij.collaboration.ui.codereview.editor.CodeReviewComponentInlayRenderer
//import com.intellij.collaboration.ui.codereview.editor.CodeReviewEditorGutterChangesRenderer
//import com.intellij.collaboration.ui.codereview.editor.CodeReviewEditorGutterControlsRenderer
//import com.intellij.collaboration.ui.codereview.editor.action.CodeReviewInEditorToolbarActionGroup
//import com.intellij.collaboration.ui.codereview.editor.controlInlaysIn
//import com.intellij.collaboration.util.getOrNull
//import com.intellij.openapi.actionSystem.Constraints
//import com.intellij.openapi.actionSystem.DefaultActionGroup
//import com.intellij.openapi.actionSystem.Separator
//import com.intellij.openapi.components.Service
//import com.intellij.openapi.components.service
//import com.intellij.openapi.components.serviceAsync
//import com.intellij.openapi.editor.Editor
//import com.intellij.openapi.editor.EditorKind
//import com.intellij.openapi.editor.event.EditorFactoryEvent
//import com.intellij.openapi.editor.event.EditorFactoryListener
//import com.intellij.openapi.editor.ex.EditorEx
//import com.intellij.openapi.editor.ex.EditorMarkupModel
//import com.intellij.openapi.editor.ex.util.EditorUtil
//import com.intellij.openapi.project.Project
//import com.intellij.openapi.util.Disposer
//import com.intellij.util.cancelOnDispose
//import kotlinx.coroutines.*
//import kotlinx.coroutines.flow.*
//import com.linqingying.gitcode.pullrequest.config.GitCodePullRequestsProjectUISettings
//import com.linqingying.gitcode.pullrequest.ui.toolwindow.model.GCPRToolWindowViewModel
//
//@OptIn(ExperimentalCoroutinesApi::class)
//@Service(Service.Level.PROJECT)
//internal class GCPRReviewInEditorController(private val project: Project, private val cs: CoroutineScope) {
//
//  internal class InstallerListener : EditorFactoryListener {
//    override fun editorCreated(event: EditorFactoryEvent) {
//      val editor = event.editor
//      editor.project?.service<GCPRReviewInEditorController>()?.setupReview(editor)
//    }
//  }
//
//  private fun setupReview(editor: Editor) {
//    if (editor !is EditorEx) return
//    if (!isPotentialEditor(editor)) return
//    val file = editor.virtualFile ?: return
//
//    val editorDisposable = Disposer.newDisposable().also {
//      EditorUtil.disposeWithEditor(editor, it)
//    }
//
//    cs.launchNow(Dispatchers.Main) {
//      val settings = project.serviceAsync<GitCodePullRequestsProjectUISettings>()
//      project.serviceAsync<GCPRToolWindowViewModel>().projectVm
//        .flatMapLatest { projectVm ->
//          projectVm?.prOnCurrentBranch?.mapScoped {
//            val id = it?.getOrNull() ?: return@mapScoped null
//            projectVm.acquireEditorReviewViewModel(id, nestedDisposable())
//          } ?: flowOf(null)
//        }.collectLatest { reviewVm ->
//          reviewVm?.getViewModelFor(file)?.collectLatest { fileVm ->
//            if (fileVm != null) {
//              val toolbarActionGroup = DefaultActionGroup(
//                CodeReviewInEditorToolbarActionGroup(reviewVm),
//                Separator.getInstance()
//              )
//              val editorMarkupModel = editor.markupModel as? EditorMarkupModel
//              editorMarkupModel?.addInspectionWidgetAction(toolbarActionGroup, Constraints.FIRST)
//
//              try {
//                val enabledFlow = reviewVm.discussionsViewOption.map { it != DiscussionsViewOption.DONT_SHOW }.distinctUntilChanged()
//                val syncedFlow = reviewVm.updateRequired.map { !it }.distinctUntilChanged()
//                combine(enabledFlow, syncedFlow) { enabled, synced -> enabled && synced }.collectLatest { enabled ->
//                  if (enabled) supervisorScope {
//                    setupReview(settings, fileVm, editor)
//                    awaitCancellation()
//                  }
//                }
//              }
//              finally {
//                editorMarkupModel?.removeInspectionWidgetAction(toolbarActionGroup)
//              }
//            }
//          }
//        }
//    }.cancelOnDispose(editorDisposable)
//  }
//
//  companion object {
//    private fun isPotentialEditor(editor: Editor): Boolean = editor.editorKind == EditorKind.MAIN_EDITOR && editor.virtualFile != null
//  }
//}
//
//private fun CoroutineScope.setupReview(settings: GitCodePullRequestsProjectUISettings,
//                                       fileVm: GCPRReviewFileEditorViewModel,
//                                       editor: EditorEx) {
//  val model = GCPRReviewFileEditorModel(this, settings, fileVm, editor.document)
//  CodeReviewEditorGutterChangesRenderer.setupIn(this, model, editor)
//  CodeReviewEditorGutterControlsRenderer.setupIn(this, model, editor)
//  editor.controlInlaysIn(this, model.inlays, { it.key }) { createRenderer(it) }
//}
//
//private fun CoroutineScope.createRenderer(model: GCPREditorMappedComponentModel): CodeReviewComponentInlayRenderer =
//  when (model) {
//    is GCPREditorMappedComponentModel.Thread<*> -> GCPRReviewThreadEditorInlayRenderer(this, model.vm)
//    is GCPREditorMappedComponentModel.NewComment<*> -> GCPRNewCommentEditorInlayRenderer(this, model.vm)
//  }
//
